﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ReadeAssetManager
{
    public partial class frmAsset : Form
    {
        private AMSServiceRef.User _user;
        private AMSServiceRef.Asset _asset;
        private const string INVALID_INPUT = "The name field cannot be empty.  Please enter an asset name.";
        private const string VERIFY_DELETE = "You are about to delete this asset and all associated records.\n\n" + 
                                             "Are you sure you want to delete this asset?";
        private const string ERROR_LOAD_ASSET = "An error occurred while loading this asset record.";

        /// <summary>
        /// Constructor.
        /// This overload is called for a new AMSServiceRef.Asset record.
        /// </summary>
        /// <param name="CurrentUser">[AMSServiceRef.User] The current application user.</param>
        public frmAsset(AMSServiceRef.User CurrentUser)
        {
            InitializeComponent();
            _user = CurrentUser;
            _asset = new AMSServiceRef.Asset();
            _asset.Owner = _user;
            this.Text = "New Asset";
        }

        /// <summary>
        /// Constructor.
        /// This overload is called for an existing AMSServiceRef.Asset record.
        /// </summary>
        /// <param name="CurrentAsset">[AMSServiceRef.Asset] The asset object to edit or view.</param>
        public frmAsset(AMSServiceRef.Asset CurrentAsset)
        {
            InitializeComponent();
            _asset = CurrentAsset;
            _user = _asset.Owner;
            PopulateFormOptions();
            PopulateFormValues();
        }

        /// <summary>
        /// PopulateFormValues
        /// Fills the userform fields from the global AMSServiceRef.Asset object.  Displays an
        /// error if the asset data could not be accessed (such as the Asset is not instantiated).
        /// </summary>
        private void PopulateFormValues()
        {
            try
            {
                txtName.Text = _asset.Name;
                txtManuf.Text = _asset.Manufacturer;
                txtMake.Text = _asset.Make;
                txtModel.Text = _asset.Model;
                txtSerial.Text = _asset.SerialNumber;
                txtMeta.Text = _asset.Metadata;
                txtComments.Text = _asset.Comments;
                if (_asset.Year == default(DateTime))
                    _asset.Year = DateTime.Today;
                else
                    dtpDate.Value = _asset.Year;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ERROR_LOAD_ASSET + "\n\n" + ex.Message, "Error Loading Asset");
            }
        }

        /// <summary>
        /// PopulateFormOptions
        /// Loads the form title and dropdown menu bar domains.
        /// </summary>
        private void PopulateFormOptions()
        {
            ToolStripMenuItem[] items;

            this.Text = _asset.Name;

            // Load all available purchases
            if (_asset.Purchases != null)
            {
                items = new ToolStripMenuItem[_asset.Purchases.Count];
                for (int i = 0; i < _asset.Purchases.Count; i++)
                {
                    AMSServiceRef.PurchaseData p = _asset.Purchases[i];
                    items[i] = CreateMenuItem(p, "mnuAssetPurch" + p.ID, p.Store + " " + p.Date.ToShortDateString(), new EventHandler(LoadPurchaseItem));
                }
                mnuAssetPurch.DropDownItems.AddRange(items);
            }
            else
                _asset.Purchases = new List<AMSServiceRef.PurchaseData>();

            // Load all available warranties
            if (_asset.Warranties != null)
            {
                items = new ToolStripMenuItem[_asset.Warranties.Count];
                for (int i = 0; i < _asset.Warranties.Count; i++)
                {
                    AMSServiceRef.WarrantyData w = _asset.Warranties[i];
                    items[i] = CreateMenuItem(w, "mnuAssetWarr" + w.ID, w.Type, new EventHandler(LoadWarrantyItem));
                }
                mnuAssetWarr.DropDownItems.AddRange(items);
            }
            else
                _asset.Warranties = new List<AMSServiceRef.WarrantyData>();

            // Load all available scheduled maintenance
            if (_asset.Schedules != null)
            {
                items = new ToolStripMenuItem[_asset.Schedules.Count];
                for (int i = 0; i < _asset.Schedules.Count; i++)
                {
                    AMSServiceRef.ScheduleData s = _asset.Schedules[i];
                    items[i] = CreateMenuItem(s, "mnuAssetSched" + s.ID, s.Title, new EventHandler(LoadScheduleItem));
                }
                mnuAssetSched.DropDownItems.AddRange(items);
            }
            else
                _asset.Schedules = new List<AMSServiceRef.ScheduleData>();

            // Load all available service work
            if (_asset.Services != null)
            {
                items = new ToolStripMenuItem[_asset.Services.Count];
                for (int i = 0; i < _asset.Services.Count; i++)
                {
                    AMSServiceRef.ServiceData s = _asset.Services[i];
                    items[i] = CreateMenuItem(s, "mnuAssetServ" + s.ID, s.Title + " " + s.Date.ToShortDateString(), new EventHandler(LoadServiceItem));
                }
                mnuAssetServ.DropDownItems.AddRange(items);
            }
            else
                _asset.Services = new List<AMSServiceRef.ServiceData>();

            // Load all available images
            if (_asset.Images != null)
            {
                items = new ToolStripMenuItem[_asset.Images.Count];
                for (int i = 0; i < _asset.Images.Count; i++)
                {
                    AMSServiceRef.AMSImage a = _asset.Images[i];
                    items[i] = CreateMenuItem(a, "mnuAssetImages" + a.ID, a.Caption, new EventHandler(LoadImageItem));
                }
                mnuAssetImages.DropDownItems.AddRange(items);
            }
            else
                _asset.Images = new List<AMSServiceRef.AMSImage>();
        }

        /// <summary>
        /// CreateMenuItem
        /// Creates a ToolStripMenuItem to represent the domain record for this Asset.
        /// </summary>
        /// <param name="TagItem">[object] The domain object to be added to the MenuItem tag.</param>
        /// <param name="Name">[string] The MenuItem name.</param>
        /// <param name="Text">[string] The MenuItem text.</param>
        /// <param name="ClickEvent">[EventHandler] The event that should be raised when the user clicks the MenuItem.</param>
        /// <returns>[ToolStripMenuItem] The menu item representing this domain object.</returns>
        private ToolStripMenuItem CreateMenuItem(object TagItem, string Name, 
                                                string Text, EventHandler ClickEvent)
        {
            ToolStripMenuItem tsmi = new ToolStripMenuItem();
            tsmi.Name = Name;
            tsmi.Text = Text;
            tsmi.Tag = TagItem;
            tsmi.Click += ClickEvent;

            return tsmi;
        }

        /// <summary>
        /// LoadPurchaseItem
        /// EventHandler for a Purchase MenuItem.
        /// </summary>
        /// <param name="sender">[object] The MenuItem that raised this event.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void LoadPurchaseItem(object sender, EventArgs e)
        {
            // Open the purchase form with ((ToolStripMenuItem)sender).Tag
            frmPurchase frmP = new frmPurchase((AMSServiceRef.PurchaseData)((ToolStripMenuItem)sender).Tag);
            frmP.MdiParent = this.MdiParent;
            frmP.Show();
        }

        /// <summary>
        /// LoadWarrantyItem
        /// EventHandler for a Warranty MenuItem.
        /// </summary>
        /// <param name="sender">[object] The MenuItem that raised this event.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void LoadWarrantyItem(object sender, EventArgs e)
        {
            // Open the warranty form with ((ToolStripMenuItem)sender).Tag
            frmWarranty frmW = new frmWarranty((AMSServiceRef.WarrantyData)((ToolStripMenuItem)sender).Tag);
            frmW.MdiParent = this.MdiParent;
            frmW.Show();
        }

        /// <summary>
        /// LoadScheduleItem
        /// EventHandler for a Schedule MenuItem.
        /// </summary>
        /// <param name="sender">[object] The MenuItem that raised this event.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void LoadScheduleItem(object sender, EventArgs e)
        {
            // Open the schedule form with ((ToolStripMenuItem)sender).Tag
            frmSchedule frmS = new frmSchedule((AMSServiceRef.ScheduleData)((ToolStripMenuItem)sender).Tag);
            frmS.MdiParent = this.MdiParent;
            frmS.Show();
        }

        /// <summary>
        /// LoadServiceItem
        /// EventHandler for a Service MenuItem.
        /// </summary>
        /// <param name="sender">[object] The MenuItem that raised this event.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void LoadServiceItem(object sender, EventArgs e)
        {
            // Open the service form with ((ToolStripMenuItem)sender).Tag
            frmService frmS = new frmService((AMSServiceRef.ServiceData)((ToolStripMenuItem)sender).Tag);
            frmS.MdiParent = this.MdiParent;
            frmS.Show();
        }

        /// <summary>
        /// LoadImageItem
        /// EventHandler for an Image MenuItem.  This functionality is not implemented.
        /// </summary>
        /// <param name="sender">[object] The MenuItem that raised this event.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void LoadImageItem(object sender, EventArgs e)
        {
            // Open the images form with ((ToolStripMenuItem)sender).Tag
            MessageBox.Show("Images are not yet implemented.", "Not Implemented");
        }

        private void mnuAssetRecordsPurchNew_Click(object sender, EventArgs e)
        {
            frmPurchase frmP = new frmPurchase(_asset);
            frmP.MdiParent = this.MdiParent;
            frmP.Show();
        }

        private void mnuAssetRecordsServNew_Click(object sender, EventArgs e)
        {
            frmService frmS = new frmService(_asset);
            frmS.MdiParent = this.MdiParent;
            frmS.Show();
        }

        private void mnuAssetRecordsSchedNew_Click(object sender, EventArgs e)
        {
            frmSchedule frmS = new frmSchedule(_asset);
            frmS.MdiParent = this.MdiParent;
            frmS.Show();
        }

        private void mnuAssetRecordsWarrNew_Click(object sender, EventArgs e)
        {
            frmWarranty frmW = new frmWarranty(_asset);
            frmW.MdiParent = this.MdiParent;
            frmW.Show();
        }

        private void mnuAssetAssetSave_Click(object sender, EventArgs e)
        {
            if (!SaveAsset())
                MessageBox.Show("Unable to save changes.");
        }

        /// <summary>
        /// PopulateAssetFormFields
        /// Loads all values from the userform into the current AMSServiceRef.Asset object.
        /// </summary>
        private void PopulateAssetFormFields()
        {
            _asset.Name = txtName.Text;
            _asset.Manufacturer = txtManuf.Text;
            _asset.Make = txtMake.Text;
            _asset.Model = txtModel.Text;
            _asset.Metadata = txtMeta.Text;
            _asset.Year = dtpDate.Value;
            _asset.Comments = txtComments.Text;
            _asset.SerialNumber = txtSerial.Text;
        }

        /// <summary>
        /// SaveAsset
        /// Validates the user input, hydrates the object from the userform controls, and attempts
        /// to save the asset.  If the save is successful, attempts to add a new Asset to the user's
        /// asset list and refreshes the frmMain asset list.
        /// </summary>
        /// <returns>[bool] True if the asset was successfully saved, otherwise false.</returns>
        private bool SaveAsset()
        {
            if (IsValidInput())
            {
                PopulateAssetFormFields();
                AMSServiceRef.AMSServiceClient c = new AMSServiceRef.AMSServiceClient();
                AMSServiceRef.Asset tmpa = c.SaveAsset(_asset);
                if (tmpa != null)
                {
                    _asset = tmpa;
                    _user = _asset.Owner;
                    //AddAssetToUser();
                    ((frmMain)MdiParent).RefreshAssetList(_user);
                    return true;
                }
                return false;
            }
            else
            {
                MessageBox.Show(INVALID_INPUT);
                return false;
            }
        }

        private void mnuAssetAssetSaveClose_Click(object sender, EventArgs e)
        {
            if (!SaveAsset())
            {
                if (MessageBox.Show("Unable to save changes.  Do you still want to close?", "Save Failed", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
                    return;
            }
            this.Close();
        }

        /// <summary>
        /// IsValidInput
        /// Validates the user input based on database requirements.
        /// </summary>
        /// <returns>[bool] True if the input is valid, otherwise false.</returns>
        private bool IsValidInput()
        {
            return txtName.Text.Length > 0;
        }

        /// <summary>
        /// AddAssetToUser
        /// Determines whether the current asset already exists in the AMSServiceRef.User asset
        /// list.  If not, this asset is added.  If so, simply returns.
        /// </summary>
        private void AddAssetToUser()
        {
            if (_asset.Owner.Assets != null)
            {
                foreach (AMSServiceRef.Asset a in _asset.Owner.Assets)
                {
                    if (a.Equals(_asset))
                        return;
                }
            }
            else
                _asset.Owner.Assets = new List<AMSServiceRef.Asset>();

            _asset.Owner.Assets.Add(_asset);
        }

        private void mnuAssetAssetDelete_Click(object sender, EventArgs e)
        {
            if (_asset.ID > 0)
            {
                if (MessageBox.Show(VERIFY_DELETE, "Delete Asset", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                {
                    AMSServiceRef.AMSServiceClient c = new AMSServiceRef.AMSServiceClient();
                    if (c.DeleteAsset(_asset))
                    {
                        _user.Assets.Remove(_asset);
                        ((frmMain)MdiParent).RefreshAssetList(_user);
                        this.Close();
                    }
                    else
                        MessageBox.Show("Unable to delete asset " + _asset.Name + ".");
                }
            }
        }
    }
}
